{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "Exercise 5 - Question.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "collapsed_sections": []
    },
    "kernelspec": {
      "name": "python3",
      "display_name": "Python 3"
    },
    "accelerator": "GPU"
  },
  "cells": [
    {
      "cell_type": "code",
      "metadata": {
        "id": "dn-6c02VmqiN",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# In this exercise you will train a CNN on the FULL Cats-v-dogs dataset\n",
        "# This will require you doing a lot of data preprocessing because\n",
        "# the dataset isn't split into training and validation for you\n",
        "# This code block has all the required inputs\n",
        "import os\n",
        "import zipfile\n",
        "import random\n",
        "import tensorflow as tf\n",
        "from tensorflow.keras.optimizers import RMSprop\n",
        "from tensorflow.keras.preprocessing.image import ImageDataGenerator\n",
        "from shutil import copyfile"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "3sd9dQWa23aj",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 204
        },
        "outputId": "fcba3339-7a24-4075-9f2e-357966ff89f6"
      },
      "source": [
        "# This code block downloads the full Cats-v-Dogs dataset and stores it as \n",
        "# cats-and-dogs.zip. It then unzips it to /tmp\n",
        "# which will create a tmp/PetImages directory containing subdirectories\n",
        "# called 'Cat' and 'Dog' (that's how the original researchers structured it)\n",
        "# If the URL doesn't work, \n",
        "# .   visit https://www.microsoft.com/en-us/download/confirmation.aspx?id=54765\n",
        "# And right click on the 'Download Manually' link to get a new URL\n",
        "\n",
        "!wget --no-check-certificate \\\n",
        "    \"https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip\" \\\n",
        "    -O \"/tmp/cats-and-dogs.zip\"\n",
        "\n",
        "local_zip = '/tmp/cats-and-dogs.zip'\n",
        "zip_ref = zipfile.ZipFile(local_zip, 'r')\n",
        "zip_ref.extractall('/tmp')\n",
        "zip_ref.close()\n"
      ],
      "execution_count": 4,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "--2019-06-14 06:34:39--  https://download.microsoft.com/download/3/E/1/3E1C3F21-ECDB-4869-8368-6DEBA77B919F/kagglecatsanddogs_3367a.zip\n",
            "Resolving download.microsoft.com (download.microsoft.com)... 23.33.164.200, 2600:1407:16:196::e59, 2600:1407:16:19c::e59\n",
            "Connecting to download.microsoft.com (download.microsoft.com)|23.33.164.200|:443... connected.\n",
            "HTTP request sent, awaiting response... 200 OK\n",
            "Length: 824894548 (787M) [application/octet-stream]\n",
            "Saving to: ‘/tmp/cats-and-dogs.zip’\n",
            "\n",
            "/tmp/cats-and-dogs. 100%[===================>] 786.68M  25.2MB/s    in 32s     \n",
            "\n",
            "2019-06-14 06:35:12 (24.5 MB/s) - ‘/tmp/cats-and-dogs.zip’ saved [824894548/824894548]\n",
            "\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "gi3yD62a6X3S",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        },
        "outputId": "a0d6fc48-0add-4ca5-f7bb-774ab7c94977"
      },
      "source": [
        "print(len(os.listdir('/tmp/PetImages/Cat/')))\n",
        "print(len(os.listdir('/tmp/PetImages/Dog/')))\n",
        "\n",
        "# Expected Output:\n",
        "# 12501\n",
        "# 12501"
      ],
      "execution_count": 5,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "12501\n",
            "12501\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "F-QkLjxpmyK2",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        "# Use os.mkdir to create your directories\n",
        "# You will need a directory for cats-v-dogs, and subdirectories for training\n",
        "# and testing. These in turn will need subdirectories for 'cats' and 'dogs'\n",
        "try:\n",
        "    os.mkdir('/tmp/cats-v-dogs')\n",
        "    os.mkdir('/tmp/cats-v-dogs/training')\n",
        "    os.mkdir('/tmp/cats-v-dogs/testing')\n",
        "    os.mkdir('/tmp/cats-v-dogs/training/cats')\n",
        "    os.mkdir('/tmp/cats-v-dogs/training/dogs')\n",
        "    os.mkdir('/tmp/cats-v-dogs/testing/cats')\n",
        "    os.mkdir('/tmp/cats-v-dogs/testing/dogs')\n",
        "except OSError:\n",
        "    pass"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "zvSODo0f9LaU",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        },
        "outputId": "645962e9-fffe-4a04-9c94-3e7753aaf823"
      },
      "source": [
        "# Write a python function called split_data which takes\n",
        "# a SOURCE directory containing the files\n",
        "# a TRAINING directory that a portion of the files will be copied to\n",
        "# a TESTING directory that a portion of the files will be copie to\n",
        "# a SPLIT SIZE to determine the portion\n",
        "# The files should also be randomized, so that the training set is a random\n",
        "# X% of the files, and the test set is the remaining files\n",
        "# SO, for example, if SOURCE is PetImages/Cat, and SPLIT SIZE is .9\n",
        "# Then 90% of the images in PetImages/Cat will be copied to the TRAINING dir\n",
        "# and 10% of the images will be copied to the TESTING dir\n",
        "# Also -- All images should be checked, and if they have a zero file length,\n",
        "# they will not be copied over\n",
        "#\n",
        "# os.listdir(DIRECTORY) gives you a listing of the contents of that directory\n",
        "# os.path.getsize(PATH) gives you the size of the file\n",
        "# copyfile(source, destination) copies a file from source to destination\n",
        "# random.sample(list, len(list)) shuffles a list\n",
        "def split_data(SOURCE, TRAINING, TESTING, SPLIT_SIZE):\n",
        "    files = []\n",
        "    for filename in os.listdir(SOURCE):\n",
        "        file = SOURCE + filename\n",
        "        if os.path.getsize(file) > 0:\n",
        "            files.append(filename)\n",
        "        else:\n",
        "            print(filename + \" is zero length, so ignoring.\")\n",
        "\n",
        "    training_length = int(len(files) * SPLIT_SIZE)\n",
        "    testing_length = int(len(files) - training_length)\n",
        "    shuffled_set = random.sample(files, len(files))\n",
        "    training_set = shuffled_set[0:training_length]\n",
        "    testing_set = shuffled_set[-testing_length:]\n",
        "\n",
        "    for filename in training_set:\n",
        "        this_file = SOURCE + filename\n",
        "        destination = TRAINING + filename\n",
        "        copyfile(this_file, destination)\n",
        "\n",
        "    for filename in testing_set:\n",
        "        this_file = SOURCE + filename\n",
        "        destination = TESTING + filename\n",
        "        copyfile(this_file, destination)\n",
        "\n",
        "\n",
        "\n",
        "CAT_SOURCE_DIR = \"/tmp/PetImages/Cat/\"\n",
        "TRAINING_CATS_DIR = \"/tmp/cats-v-dogs/training/cats/\"\n",
        "TESTING_CATS_DIR = \"/tmp/cats-v-dogs/testing/cats/\"\n",
        "DOG_SOURCE_DIR = \"/tmp/PetImages/Dog/\"\n",
        "TRAINING_DOGS_DIR = \"/tmp/cats-v-dogs/training/dogs/\"\n",
        "TESTING_DOGS_DIR = \"/tmp/cats-v-dogs/testing/dogs/\"\n",
        "\n",
        "split_size = .9\n",
        "split_data(CAT_SOURCE_DIR, TRAINING_CATS_DIR, TESTING_CATS_DIR, split_size)\n",
        "split_data(DOG_SOURCE_DIR, TRAINING_DOGS_DIR, TESTING_DOGS_DIR, split_size)\n",
        "\n",
        "# Expected output\n",
        "# 666.jpg is zero length, so ignoring\n",
        "# 11702.jpg is zero length, so ignoring"
      ],
      "execution_count": 7,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "666.jpg is zero length, so ignoring.\n",
            "11702.jpg is zero length, so ignoring.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "luthalB76ufC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 85
        },
        "outputId": "1802f5ea-b6bc-4937-ec3d-9f03c05ed85b"
      },
      "source": [
        "print(len(os.listdir('/tmp/cats-v-dogs/training/cats/')))\n",
        "print(len(os.listdir('/tmp/cats-v-dogs/training/dogs/')))\n",
        "print(len(os.listdir('/tmp/cats-v-dogs/testing/cats/')))\n",
        "print(len(os.listdir('/tmp/cats-v-dogs/testing/dogs/')))\n",
        "\n",
        "# Expected output:\n",
        "# 11250\n",
        "# 11250\n",
        "# 1250\n",
        "# 1250"
      ],
      "execution_count": 8,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "11250\n",
            "11250\n",
            "1250\n",
            "1250\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "-BQrav4anTmj",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 156
        },
        "outputId": "63169d33-8a2c-4327-cb76-d00e8bf4dc7e"
      },
      "source": [
        "# DEFINE A KERAS MODEL TO CLASSIFY CATS V DOGS\n",
        "# USE AT LEAST 3 CONVOLUTION LAYERS\n",
        "model = tf.keras.models.Sequential([\n",
        "    tf.keras.layers.Conv2D(32, (3, 3), activation='relu', input_shape=(150, 150, 3)),\n",
        "    tf.keras.layers.MaxPooling2D(2, 2),\n",
        "    tf.keras.layers.Conv2D(64, (3, 3), activation='relu'),\n",
        "    tf.keras.layers.MaxPooling2D(2, 2),\n",
        "    tf.keras.layers.Conv2D(128, (3, 3), activation='relu'),\n",
        "    tf.keras.layers.MaxPooling2D(2, 2),\n",
        "    tf.keras.layers.Flatten(),\n",
        "    tf.keras.layers.Dense(512, activation='relu'),\n",
        "    tf.keras.layers.Dense(1, activation='sigmoid')\n",
        "])\n",
        "\n",
        "model.compile(optimizer=RMSprop(lr=0.001), loss='binary_crossentropy', metrics=['acc'])"
      ],
      "execution_count": 9,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "WARNING: Logging before flag parsing goes to stderr.\n",
            "W0614 06:35:29.584468 140269364676480 deprecation.py:506] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/init_ops.py:1251: calling VarianceScaling.__init__ (from tensorflow.python.ops.init_ops) with dtype is deprecated and will be removed in a future version.\n",
            "Instructions for updating:\n",
            "Call initializer instance with the dtype argument instead of passing it to the constructor\n",
            "W0614 06:35:29.868237 140269364676480 deprecation.py:323] From /usr/local/lib/python3.6/dist-packages/tensorflow/python/ops/nn_impl.py:180: add_dispatch_support.<locals>.wrapper (from tensorflow.python.ops.array_ops) is deprecated and will be removed in a future version.\n",
            "Instructions for updating:\n",
            "Use tf.where in 2.0, which has the same broadcast rule as np.where\n"
          ],
          "name": "stderr"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "mlNjoJ5D61N6",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 51
        },
        "outputId": "9e6d1e87-5147-473e-b2a1-abbc48e488c0"
      },
      "source": [
        "TRAINING_DIR = \"/tmp/cats-v-dogs/training/\"\n",
        "train_datagen = ImageDataGenerator(rescale=1.0/255)\n",
        "train_generator = train_datagen.flow_from_directory(TRAINING_DIR,\n",
        "                                                    batch_size=100,\n",
        "                                                    class_mode='binary',\n",
        "                                                    target_size=(150, 150))\n",
        "\n",
        "VALIDATION_DIR = \"/tmp/cats-v-dogs/testing/\"\n",
        "validation_datagen = ImageDataGenerator(rescale=1.0/255)\n",
        "validation_generator = validation_datagen.flow_from_directory(VALIDATION_DIR,\n",
        "                                                              batch_size=100,\n",
        "                                                              class_mode='binary',\n",
        "                                                              target_size=(150, 150))\n",
        "\n",
        "\n",
        "\n",
        "# Expected Output:\n",
        "# Found 22498 images belonging to 2 classes.\n",
        "# Found 2500 images belonging to 2 classes."
      ],
      "execution_count": 10,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Found 22498 images belonging to 2 classes.\n",
            "Found 2500 images belonging to 2 classes.\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "KyS4n53w7DxC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 2791
        },
        "outputId": "a9e9d383-c2bc-4a30-ab73-26e276adbc04"
      },
      "source": [
        "history = model.fit_generator(train_generator,\n",
        "                              epochs=15,\n",
        "                              verbose=1,\n",
        "                              validation_data=validation_generator)\n",
        "\n",
        "# The expectation here is that the model will train, and that accuracy will be > 95% on both training and validation\n",
        "# i.e. acc:A1 and val_acc:A2 will be visible, and both A1 and A2 will be > .9"
      ],
      "execution_count": 11,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 18350080 bytes but only got 0. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 12 bytes but only got 6. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "Epoch 1/15\n",
            " 33/225 [===>..........................] - ETA: 1:13 - loss: 1.4527 - acc: 0.5373"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 80000 bytes but only got 0. Skipping tag 64640\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 65536 bytes but only got 0. Skipping tag 3\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 307363840 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 307888128 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 131072 bytes but only got 0. Skipping tag 3\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 328728576 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 1385474 bytes but only got 5357. Skipping tag 513\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 3846701056 bytes but only got 0. Skipping tag 2\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 3300917248 bytes but only got 0. Skipping tag 7\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 196867 bytes but only got 5357. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 12 bytes but only got 8. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            " 39/225 [====>.........................] - ETA: 1:08 - loss: 1.3352 - acc: 0.5390"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 6553600 bytes but only got 0. Skipping tag 49\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 1050744 bytes but only got 4951. Skipping tag 51\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 293339136 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 293863424 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 3368026112 bytes but only got 0. Skipping tag 7\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 134479872 bytes but only got 0. Skipping tag 7\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 295698432 bytes but only got 0. Skipping tag 10\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 296222720 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 14745600 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 25624576 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 317718528 bytes but only got 4956. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 131073 bytes but only got 4952. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 393216 bytes but only got 0. Skipping tag 3\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 287178752 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 287703040 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 524288 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 286654464 bytes but only got 4956. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 12 bytes but only got 2. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "104/225 [============>.................] - ETA: 38s - loss: 0.9406 - acc: 0.5736"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 32 bytes but only got 0. Skipping tag 270\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 5 bytes but only got 0. Skipping tag 271\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 8 bytes but only got 0. Skipping tag 272\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 8 bytes but only got 0. Skipping tag 282\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 8 bytes but only got 0. Skipping tag 283\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 20 bytes but only got 0. Skipping tag 306\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 48 bytes but only got 0. Skipping tag 532\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 2 bytes but only got 0. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "115/225 [==============>...............] - ETA: 35s - loss: 0.9109 - acc: 0.5812"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 262146 bytes but only got 0. Skipping tag 2\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 262151 bytes but only got 0. Skipping tag 56\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 12 bytes but only got 0. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "135/225 [=================>............] - ETA: 28s - loss: 0.8703 - acc: 0.5905"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 404094976 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 404619264 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 425459712 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 1385474 bytes but only got 6833. Skipping tag 513\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 196867 bytes but only got 6833. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "206/225 [==========================>...] - ETA: 5s - loss: 0.7797 - acc: 0.6204"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 209715200 bytes but only got 0. Skipping tag 48\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 52428800 bytes but only got 0. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 6468665344 bytes but only got 0. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 1050744 bytes but only got 7027. Skipping tag 48\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 422313984 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 422838272 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 428867584 bytes but only got 0. Skipping tag 10\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 429391872 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 2031616 bytes but only got 0. Skipping tag 3\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 429916160 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 21299200 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 24313856 bytes but only got 0. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 453771264 bytes but only got 7032. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 131073 bytes but only got 7028. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 416415744 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 416940032 bytes but only got 0. Skipping tag 5\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 415825920 bytes but only got 7032. Skipping tag 4\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "225/225 [==============================] - 77s 343ms/step - loss: 0.7642 - acc: 0.6257 - val_loss: 0.5649 - val_acc: 0.7140\n",
            "Epoch 2/15\n",
            "141/225 [=================>............] - ETA: 22s - loss: 0.5342 - acc: 0.7285"
          ],
          "name": "stdout"
        },
        {
          "output_type": "stream",
          "text": [
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:725: UserWarning: Possibly corrupt EXIF data.  Expecting to read 18350080 bytes but only got 0. Skipping tag 0\n",
            "  \" Skipping tag %s\" % (size, len(data), tag))\n",
            "/usr/local/lib/python3.6/dist-packages/PIL/TiffImagePlugin.py:742: UserWarning: Corrupt EXIF data.  Expecting to read 12 bytes but only got 6. \n",
            "  warnings.warn(str(msg))\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "stream",
          "text": [
            "225/225 [==============================] - 70s 312ms/step - loss: 0.5229 - acc: 0.7383 - val_loss: 0.4720 - val_acc: 0.7704\n",
            "Epoch 3/15\n",
            "225/225 [==============================] - 70s 313ms/step - loss: 0.4404 - acc: 0.7926 - val_loss: 0.4310 - val_acc: 0.7956\n",
            "Epoch 4/15\n",
            "225/225 [==============================] - 70s 312ms/step - loss: 0.3773 - acc: 0.8329 - val_loss: 0.3912 - val_acc: 0.8220\n",
            "Epoch 5/15\n",
            "225/225 [==============================] - 70s 310ms/step - loss: 0.3104 - acc: 0.8659 - val_loss: 0.3852 - val_acc: 0.8296\n",
            "Epoch 6/15\n",
            "225/225 [==============================] - 70s 310ms/step - loss: 0.2449 - acc: 0.8959 - val_loss: 0.3931 - val_acc: 0.8372\n",
            "Epoch 7/15\n",
            "225/225 [==============================] - 70s 311ms/step - loss: 0.1719 - acc: 0.9325 - val_loss: 0.4128 - val_acc: 0.8364\n",
            "Epoch 8/15\n",
            "225/225 [==============================] - 70s 310ms/step - loss: 0.1127 - acc: 0.9573 - val_loss: 0.5208 - val_acc: 0.8392\n",
            "Epoch 9/15\n",
            "225/225 [==============================] - 69s 309ms/step - loss: 0.0843 - acc: 0.9717 - val_loss: 0.8196 - val_acc: 0.8124\n",
            "Epoch 10/15\n",
            "225/225 [==============================] - 70s 311ms/step - loss: 0.0510 - acc: 0.9828 - val_loss: 0.8247 - val_acc: 0.8376\n",
            "Epoch 11/15\n",
            "225/225 [==============================] - 70s 313ms/step - loss: 0.0612 - acc: 0.9824 - val_loss: 0.8381 - val_acc: 0.8360\n",
            "Epoch 12/15\n",
            "225/225 [==============================] - 71s 315ms/step - loss: 0.0651 - acc: 0.9844 - val_loss: 0.8943 - val_acc: 0.8440\n",
            "Epoch 13/15\n",
            "225/225 [==============================] - 71s 315ms/step - loss: 0.0624 - acc: 0.9836 - val_loss: 1.4848 - val_acc: 0.7688\n",
            "Epoch 14/15\n",
            "225/225 [==============================] - 70s 313ms/step - loss: 0.0520 - acc: 0.9879 - val_loss: 1.0409 - val_acc: 0.8328\n",
            "Epoch 15/15\n",
            "225/225 [==============================] - 71s 314ms/step - loss: 0.0451 - acc: 0.9874 - val_loss: 1.0064 - val_acc: 0.8428\n"
          ],
          "name": "stdout"
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "MWZrJN4-65RC",
        "colab_type": "code",
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 562
        },
        "outputId": "a88d7cd8-0342-43dd-9842-c6814ac75ca6"
      },
      "source": [
        "# PLOT LOSS AND ACCURACY\n",
        "%matplotlib inline\n",
        "\n",
        "import matplotlib.image  as mpimg\n",
        "import matplotlib.pyplot as plt\n",
        "\n",
        "#-----------------------------------------------------------\n",
        "# Retrieve a list of list results on training and test data\n",
        "# sets for each training epoch\n",
        "#-----------------------------------------------------------\n",
        "acc=history.history['acc']\n",
        "val_acc=history.history['val_acc']\n",
        "loss=history.history['loss']\n",
        "val_loss=history.history['val_loss']\n",
        "\n",
        "epochs=range(len(acc)) # Get number of epochs\n",
        "\n",
        "#------------------------------------------------\n",
        "# Plot training and validation accuracy per epoch\n",
        "#------------------------------------------------\n",
        "plt.plot(epochs, acc, 'r', \"Training Accuracy\")\n",
        "plt.plot(epochs, val_acc, 'b', \"Validation Accuracy\")\n",
        "plt.title('Training and validation accuracy')\n",
        "plt.figure()\n",
        "\n",
        "#------------------------------------------------\n",
        "# Plot training and validation loss per epoch\n",
        "#------------------------------------------------\n",
        "plt.plot(epochs, loss, 'r', \"Training Loss\")\n",
        "plt.plot(epochs, val_loss, 'b', \"Validation Loss\")\n",
        "\n",
        "\n",
        "plt.title('Training and validation loss')\n",
        "\n",
        "# Desired output. Charts with training and validation metrics. No crash :)"
      ],
      "execution_count": 12,
      "outputs": [
        {
          "output_type": "execute_result",
          "data": {
            "text/plain": [
              "Text(0.5, 1.0, 'Training and validation loss')"
            ]
          },
          "metadata": {
            "tags": []
          },
          "execution_count": 12
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "iVBORw0KGgoAAAANSUhEUgAAAcsAAAEICAYAAAAwft9dAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4zLCBo\ndHRwOi8vbWF0cGxvdGxpYi5vcmcvnQurowAAIABJREFUeJzt3XmcVXX9x/HXGyZEQNncEFRw+Wnm\ngoIbCqZZmru5ouWSaz8tLSv3cqusTDMryx+/MnfRNJdfKu4YboGKCpqooIKAsoogyDCf3x/fc+Uy\nzL1nBma4s7yfj8d9zLnnnnvu556Zue/7/Z7lq4jAzMzMSmtX6QLMzMyaO4elmZlZDoelmZlZDoel\nmZlZDoelmZlZDoelmZlZDoelWT1Iai/pE0kbNuaylSRpU0mNfu6YpL0kTSq6/x9Jg+uz7Aq81jBJ\n56/o883qq6rSBZg1BUmfFN3tBCwClmT3T42IWxqyvohYAnRp7GXbgojYvDHWI+kk4JsR8eWidZ/U\nGOs2y+OwtFYpIj4Pq6zlclJEPFpqeUlVEVG9Kmozy+O/x+bH3bDWJkm6XNIdkm6TNA/4pqRdJD0n\naY6kqZJ+J+kL2fJVkkJS3+z+zdnjD0qaJ+lZSf0aumz2+NclvSlprqRrJY2SdHyJuutT46mS3pI0\nW9Lvip7bXtLVkmZKegfYp8z2uUDS7bXm/UHSVdn0SZJez97P21mrr9S6Jkv6cjbdSdJNWW3jgAG1\nlr1Q0jvZesdJOjCbvzXwe2Bw1sU9o2jbXlz0/NOy9z5T0j8k9arPtmnIdi7UI+lRSbMkTZP046LX\nuSjbJh9LGi1p/bq6vCX9q/B7zrbnyOx1ZgEXStpM0hPZa8zItlvXoudvlL3Hj7LHr5HUMav5i0XL\n9ZK0QFLPUu/X8jksrS07BLgV6ArcAVQDZwJrAbuSwuTUMs8/GrgI6AG8B1zW0GUlrQMMB36Uve5E\nYMcy66lPjfuSQmg70peAvbL53wG+BmwL7AAcUeZ1bgP2l9Q5q7MKOJy0vQCmA/sBawInA9dK2qbM\n+gouBTYANs7qPK7W429m76sr8DPgVknrRsSrwBnA0xHRJSLWqr1iSV/L1n8Y0Bv4AKjd3V5q29RW\ncjtngfUocD/QC/gv4MnseT/KXn8foBtwErCw3AYpMgh4HVgb+CUg4HJgPWBL0ja7KKuhCvg/4C2g\nL2mbDo+IhaS/p28Wrfdo4OGImFnPOqwuEeGbb636BkwC9qo173Lg8Zzn/RC4M5uuAgLom92/GfhT\n0bIHAq+twLLfJgVA4TEBU4Hj6/ne6qpx56LH7wZ+mE2PJHVHFx7bN30ElFz3c8DR2fTXgf+UWfYB\n4PRsei9gUtFjk4EvZ9PvFf8ugP8uXraO9b4G7JdNnwQ8Wevxm4GLs+m/AT8vemxN0n7qPnnbpoHb\n+VvAv0ss93ah3lrzN629rYF/FX7P2Xt7J6eGwwqvCwwGpgHt61huV9KXLmX3Xwa+0dj/V23t5pal\ntWXvF9+RtIWk/8u61T4mtVKWa8EUmVY0vYDyB/WUWnb94joifbpNLrWSetZYr9cC3i1TL6RW5NBs\n+miWtiqRtL+k57MuwjmkFmu5bVXQq1wNko6XNDbrSpwDbFHP9UJ6f5+vLyI+BmaTWpkF9fqd5Wzn\nDUihWJdyj+Wp/fe4nqThkqZkNdxQq4ZJkQ4mW0ZEjCK1jHeTtBWwIakVaivBYWltWe3TJv5Masls\nGhFrAj8htfSa0lRSywcASWLZD/faVqbGqaQP2YK8U1uGA3tJ6g0cRBaWklYH7gJ+AawbEd2AEfWs\nY1qpGiRtDFxH6i7uma33jaL15p3m8gGwUdH61gC6A1PqUVdt5bbz+8AmJZ5X6rH5WU2diuatV2uZ\n2u/vl6SjuLfOaji+Vg0bSWpfoo4bSV2x3yJ1zy4qsZzVk8PSbKk1gLnA/OwAiXL7KxvLA8D2kg7I\n9kOdSdpn1RQ1DgfOktQ7O9jjnHILR8Q0UlfhDaQu2AnZQ6sBHYCPgCWS9ge+0oAazpfUTek81DOK\nHutCCoyPSN8bTia1LAumA32KD7Sp5TbgREnbSFqNFOZPR0TJlnoZ5bbzfcCGks6QtJqkNSUV9jMP\nAy6XtImS/pJ6kL4kTCPtJ20v6RSKgr1MDfOBuZI2IHUFFzwLzAR+rnTQ1OqSdi16/CZSt+3RpOC0\nleSwNFvqbNIBJ/NILYs7mvoFI2I6cCRwFenDbxPgJVKLorFrvA54DHgV+DepdZjnVtI+yM+7YCNi\nDvB94B5gFulD+YF61vBTUgt3EvAgRR/kEfEKcC3wQrbM5sDzRc99BJgATJdU3J1aeP5DpO7Se7Ln\nbwgcU8+6aiu5nSNiLvBV4FBSgL8J7J49/GvgH6Tt/DFwPdAx614/GTgfmEHah1n83uryU9LBXnNJ\nAf33ohqqgf2BL5Jame+Rfg+FxyeRfs+LIuKZBr53q0NhB7CZNQNZt9oHwGER8XSl67GWS9KNpIOG\nLq50La2BL0pgVmGS9iEdefopcB6wmNS6Mlsh2f7fg4CtK11La+FuWLPK2w14h7Svbm/gEB+QYStK\n0i+AsaTTaN6rdD2thbthzczMcrhlaWZmlsP7LFuJtdZaK/r27VvpMszMWowxY8bMiIhyp2p9zmHZ\nSvTt25fRo0dXugwzsxZDUt5VrD7nblgzM7McDkszM7McDkszM7McDkszM7McDkszM7McZcNS0hOS\n9q417yxJ1+U875Ps5/qS6rxYs6QnJQ3MWc9ZxUPaSPqnpG7lntMQkl6WdHtjrc/MzFqnvJblbcBR\nteYdlc3PFREfRMRh+UuWdBbweVhGxL7ZiAcrLRt2pz0wWFLnxlhnidfx6TlmZi1cXljeBewnqQOA\npL6k0cifltRF0mOSXpT0qqSDaj9ZUl9Jr2XTq0u6XdLrku4BVi9a7jpJoyWNk3RJNu972Ws9IemJ\nbN4kSWtl0z+Q9Fp2O6vo9V6X9D/ZukZkA9XWZShpzLcRpAsOF2rZVNKj2WjtL0raJJt/TvY+x0q6\nIpv3eetY0lqSJmXTx0u6T9LjwGPltpWkYyW9kq33JklrSJpYGLMvGyvv8/tmZrbqlW31RMQsSS8A\nXwfuJbUqh0dESFpIuuDzx1mAPSfpvih9sdnvAAsi4ouStgFeLHrsguy12pPCZZuI+J2kHwB7RMSM\n4hVJGgCcAOxEGjn8eUlPAbOBzYChEXGypOGkMedurqOeI0lj0m0BfJel4/XdAlwREfdI6gi0k/R1\nUqDuFBELssFc82wPbJO9r6q6thWwJXAhMCgiZkjqERHzJD0J7EcaF+8o4O6IWFz7BbIBZE8B2HDD\nvEHvzcxsRdWni7DQFVsIyxOz+SKN0j0EqAF6A+uSRgOvyxDgd5AGeZX0StFjR2Qf/FVAL1KIvLL8\nKj63G3BPRMwHkHQ3MJg0QOrEiHg5W24M0Lf2k7PW4IyIeE/SFOAvWQAuBnpHxD1ZnQuz5fcC/hoR\nC7L5s8rUVvBI0XKlttWewJ2FLwNFyw8DfkwKyxNIg8YuJyKuJw0uy8CBA31FfDNrXmpqYOFCWLAg\n/QSQlr21a7f8vPreCs/9QtN3vNUnLO8Frpa0PdApIsZk848B1gYGRMTirAuyY0MLkNQP+CGwQ0TM\nlnTDiqynSPHQRkso6u4tMhTYotBtCqxJaoE29GCfapZ2ZdeueX7RdIO2VUSMyrqUvwy0j4jXGliX\nmTXUokUwY0b6gF/RD+9SN4DFi6G6etmfdc0r9bOueREpMAqhUW467/Hi0Fq0KAXcp5+mn3XdSj1W\nPP/TT5v+97buujCtVBut8eSGZUR8ku0z/AvLHtjTFfgw+/DfA9goZ1UjgaOBxyVtBWyTzV+TFCxz\nJa1L6vJ9MntsHrAGMGPZVfE0cEO271DAIcC38t4LgKR2wBHA1hHxQTZvD+CiiPgfSZMlHRwR/5C0\nGukgoEeAn0i6pdANm7UCJwEDSAP1ljuQqdS2ehy4R9JVETGzaL0AN5K6hi+rz/sysxIWL4bp0+GD\nD8rfZs6sdKXNX8eO0KlT3beePeuev/rq6WfHrH0Qsfytpqbu+fW5depUvuZGUt8jNW8D7mHZI2Nv\nAe6X9CowGngjZx3XAX+V9DrwOqmLlIgYK+ml7PnvA6OKnnM98JCkDyJij8LMiHgxa4EWRpMfFhEv\nZQcg5RkMTCkEZWYksKWkXqTQ/bOkS0ndsodHxEOS+gOjJX0G/BM4H7gSGJ51If9fmdesc1tFxDhJ\nPwOekrQEeAk4vug5l1PPI4/N2pwlS+DDD/ND8KOP0odqsfbtYb31YP31YeONYbfd0vQ666QW1op+\ncJe6Qeoq/MIXoKqq7p/lHiu1jLQ0bAqBU3s67/G6pldbbfnQ69gxbZs2yoM/N1OSDgMOioh6tZgH\nDhwYHnXEWpWaGpg6Fd55ByZOXP7n1KlpmWJSCrz11y9/W3vtFJjWpkkaExFlz/cv8DmAzZCka0nd\n0ftWuhazJjV3bt1B+M47MGlS2ndWIEHv3qkluNdesMEGywZgr15p/9UqONjD2h6HZTMUEd+tdA1m\njaK6OoVeqUCcVevA8m7dUhhutRUceCD065fu9+sHG22UugfNKsBhaWaNZ8YMePZZeOaZ9POFF5Y9\nIrJDB+jbN4XfDjssG4b9+kH37hUr3awch6WZrZglS2D8+KXB+MwzMGFCeqyqCrbfHk45Bfr3T4G4\n8capu7QNHyRiLZfD0szqZ84ceP75pcH43HMwb156bJ11YJdd4KSTYNAgGDAgnTJg1ko4LM1seRHw\n5pvLthrHj196EvzWW8M3v5kCctCg1GosnHxv1go5LM0sHXVaCMVCq7Fwkn63brDzznDkkSkYd9wR\n1lijsvWarWIOS7O2atEiGDEChg+H++6Djz9O87fYAg46KAXjLruk+97PaG2cw9KsLVm4MAXknXcu\nDcju3eHQQ+GQQ2DXXaFHfQbVMWtbHJZmrV1xQN57bzoop3t3OOwwOPxw2HPPdEqHmZXksDRrjUoF\n5OGHp9tXvuIr3Zg1gMPSrLUoBGRhH2RxQB5xRGpBOiDNVojD0qwlW7gQHn546T5IB6RZk3BYmrU0\ndQVkjx4pHAv7IB2QZo3KYWnW3EXA22+nLtYRI+Cxx+CTTxyQZquQw9KsOZozBx5/fGlATpyY5vft\nC8cck07zcECarTIOS7PmoLo6XXe1EI4vvJAGNl5jjRSKP/whfO1rsMkmvqycWQU4LM0qpbhr9fHH\n0wUC2rVLQ1ddcEEKx512cuvRrBlwWJqtKnPmwBNPLA3Id95J8zfaCI46KoXjnnt6TEezZshhadZU\nqqvh3/9eGo7PP5/GgOzSJYXiD36QAnLTTd21atbMOSzNGtPs2fDgg3D//fDQQ6k1KaWu1fPOS+G4\n887uWjVrYRyWZivrP/9J4fjAA/Cvf6XW4zrrwMEHw777pkvL+eLkZi2aw9KsoRYvTqH4wAMpJCdM\nSPO32QbOOQcOOCCN+ehhrcxaDYelWX3MmpW6VYu7Vzt0gD32gDPPhP33TwfqmFmr5LA0K6XQvXr/\n/TBq1NLu1UMOSa3Hr341Haxj1sgiYO7c9B1t5sx0K0wX/9xlF/jOd9pOJ8bixfDhhzB9Okybln5W\nV8PJJzf9aysimv5VrMkNHDgwRo8eXekyWrZC92ph/2Nx9+oBB6TbDjus0k+miHRlu1mz0m327NSo\nhVRG7Zu04vMj4LPP0m3Rosb7ud56MGQI7L57ugBRczzwd/FieOklePXVtB2qqtKtffvGma6urjv4\n6grBmTPT73nJktL1du2avqdNmZK27Q03QL9+q2xzNaq6ArBwK74/bVraRrV17173/PqQNCYiBtZr\nWYdl6+CwXEELF6aLkd9zTzqKde7c1L26556pa7WRulcXL04fgIXAKw6/ctOzZ6cP2uZstdXSrUOH\n5X926JBOJy18mPXpk0JzyJB023zzyoTnrFnw7LOpw+CZZ9IFkz79dNXX0akT9OyZbj16LD9d17zu\n3VMAR8Df/pb2AtTUwFVXwUknNc8vI1Onws03p3CvHYalgq5Ll/RFa911l96K7xdPd+q0YnU5LNsg\nh2UD1NSkT8kbb0wjd8ydm7pX99uvbPdqoZXXkLArTM+bV76kbt3Sh2CPHulWbrpr19QSrKlZ/hbR\nsPnFj0HdgVcuDKuq8j+ca2pg/HgYORKeeir9nDYtPbbOOkuDc/fdYautGr/hHpE6CQrBOGoUvP56\neqx9e9huO9h113QbMCC9r+rqdFuyZOl0Q+8XT7drV3cQduy48u/vvffghBPSRaD23ReGDYNevVZ+\nvY1h0SL47W/h8svT/06XLuVDr/j+igZgQzgs2yCHZT1MmAA33ZS+4k6cCJ0789nBRzBmx+/wdrcB\nzJrTrmwLb9as8q28Dh2WDbXu3Ze2BMqFYLdu6UO7rYiAt95aGpxPPZU+8CFtk912W9r63G67FMgN\nsXAhjBmTQrEQkDNmpMe6dYNBg9Jt111Tr3rnzo37/iqhpgb+8Id0MHbHjvDHP6aLQlVKRNqT8YMf\npN/1AQfAb34Dm21WuZrq4rBsgxyWJcyaBXfckULy2WeZT2ee2/6/GbnhMTw960s89++q5brfunbN\nb93VNb366s2zC6wlePfdZVuehd3FXbqkUCu0PAcOTK3aYtOnp0AstBrHjEn7SyFdHKnQahw0CL74\nxdZ9MMybb8Kxx6aLRR1xRArNnj1XbQ1vvAFnnZWGXN1ii9Sy3HvvVVtDfTks2yCHZZHPPoN//hNu\nuolZ949i1OIdGNnzGzzdeW/GfNCL6mrRrh307w+DB6cP4q22Sh8qXbs2vCVjjW/q1BSahQAdNy7N\n79gxXQBp0CCYPDkF5Ftvpcc6dEhhWmg1DhqUunnbmupq+NWv4OKL09/0sGFpD0NTmzsXLrkErr02\ndaFefDGccUbzvliVw7INavNhGQEvvMAHf7qPp++azshPtuPp9nvw6pItAejQIdhxR30ejoMGwZpr\nVrhmq7cZM9KByoWW58svpyAoDsYBAxpnH2Br8fLLqZX56qtw4onpAKCm+JtfsgT++lc4//z0ezrx\nRPjZz1rGFxWHZRvUFsMyAt5+ajIjr3mJpx//jJEf9+cdNgGgc8dqdh3cjsFD2jFkSLqgjj9IW4+F\nC1N3rLu9y1u0KLXwfvUr2HDDdIrJ7rs33vpHjYLvfQ9efDF9abnmmvSlpaVoSFi6w8lajCVLUnfc\nyBGf8vTwqYwc25Vpn/UB+tCzai6Dt5vN6Yd+ypC9V6d//yp3p7Zi/uJTP6utBr/4RTrA5thj0wWn\nzjortfxWX33F1zt5cjqY6NZboXdvuOUWGDq0dX958ceJNVuffJIOVCgcuPHsv6r5eH4VsDp9+AJ7\nrvEMQ/Zpz+AztmWLr/SmXbuulS7ZrFkaNAjGjoUf/xiuvjqdUnzTTWkfb0MsXJiOav35z9OX1wsv\nhHPPbR1HFOdxWFqz8f77yx7uP3Zs+oeUgi91msTQ+Q8zqPMrDDmkJxudvj/aaf/W/VXWrBF17pxO\nLzn44HRe5s47wwUXpMDLOwgnAv7xDzj77HTW1Te+AVde2XKvGrQiHJZWEdXVKQwLrcZRo1LXDqR/\n6p12Cs47+l12ffmP7Pzq9XTrvBpc8mM47ddt42usWRP56lfhtdfSvsZLL03nQ954I3zpS3UvP25c\nukrQY4+lZR59NI0619Y4LG2VmDMHnntuaavx+edh/vz0WJ8+RefC7RJsO+sJqi6/GG56Ol3O4+qL\n4ZRTVs0lPczagG7dUkAefDCcdlo6KOfyy+H73196gYzZs+GnP03naq65Zjol5LTT2u6pVW30bVtT\nmzgxHepfaDWOG5e6cgrnN55wwtKA3GAD0oOPPAJnXpLStHfv9N954okrdySCmZX0jW+kKyadeir8\n6EfpMsn/+7+p9XjRRSkwTz01tUDXWqvS1VaWw9Ia1SuvwE9+Avfem+6vuWYaRuiII9JBBjvtVOuy\nqxHw4EPpbObnn0/J+cc/pjT1IY9mTW6ddeDuu9MBP9/9LvzXf6X5Q4bA734H225b2fqaC4elNYrX\nX09dNnfema6Cc/HF6VvrlluWuO5p4eKRl14Ko0enkT3+/Gc47rjlr2dmZk1KWnpqyWWXwV57weGH\n+/i5Yg5LWylvvZUahbfemnYpXnBBOmKue/cST4hIzc5LL00DCPbrl67H9a1vpeuVmVnFbLABXH99\npatonhyWtkLefTd9A73hhpRxZ5+dzuEquV+jpiaNGXnZZekw2E03TdfIOuaY5n3xSDMzHJbWQFOm\npKt/DBuWumhOPx3OOy8dtFqnmhq4664Ukq+9lkb7vemmNH5QWz2szsxaHH9aWb1Mnw5XXAHXXZcu\nFHDSSanLtU+fEk9YsgSGD0/Ho48fn8ZGuvXWdKRPWxq80cxaBYellTVzZroI8+9/ny7KfOyx6ZDy\nslfueOMNOOSQ9HOrrdJ4koce6pA0sxbLYWl1mjMnDenz29+ma7QOHZqOdi0cVl7ShAmw555Lu18P\nOaR1j7ZrZm2Cw9KWMW9eOrfqyitTYB52WDoNpNSlsJYxcWIKysWL4ckn6/kkM7Pmz2FpACxYkC6y\n/Mtfpq7XAw5IZ3f071/PFbz3XjpJa8ECePxxB6WZtSruH2vjFi5MLcmNN06nfgwYkC6kc999DQjK\nKVNSUM6dmy5Z50t+mFkr45ZlGzZ3Lmy9dRoa68tfTrsYd9utgSuZOjV1vX70Ubqg5PbbN0WpZmYV\n5bBsw7p2heOPT0G5554rsIIPP0xj9UyZAiNGwI47NnKFZmbNg8Oyjbv00hV84owZ6QKSkybBQw+l\nq6SbmbVSDktruFmz0giyEyaki6EPGVLpiszMmpTD0hpm7lzYe+90VZ777mubQ6abWZvjsLT6mzcP\n9tknXQj97rtTaJqZtQEOS6uf+fNh333T2JN33gn771/piszMVhmHpeVbsCBdpeCZZ+D22+Hggytd\nkZnZKuWwtPIWLkzh+OSTcPPNafh0M7M2xlfwsdIWLUqjhTz6aBqo+eijK12RmVlFuGVpdVu8GI48\nEv75T7j+ejjuuEpXZGZWMW5Z2vKqq1Mr8t5700CWJ59c6YrMzCrKYWnLWrIkjfB8111pQMvTT690\nRWZmFeewtKVqauDb34bbbktjdX3/+5WuyMysWXBYWlJTA6eeCjfeCJddlsbrMjMzwGFpABFwxhkw\nbBhcdBFceGGlKzIza1Yclm1dROpuve46OOccuOSSSldkZtbsOCzbsojU3XrNNSkwf/ELkCpdlZlZ\ns+OwbMtmz4bhw9MRr7/5jYPSzKwEX5SgLevRI10YvWdPB6WZWRkOy7Zu7bUrXYGZWbPnblgzM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDksz\nM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7McDkszM7Mc\nDkszM7McDkszM7McDkszM7McKx2WknpKejm7TZM0peh+h3qu46+SNs9Z5nRJx6xsvUXrW1dStaST\nGmudZmbWOlWt7AoiYibQH0DSxcAnEXFl8TKSBCgiakqs44R6vM4fVrbWWo4AngWGAsMaed2fk1QV\nEdVNtX4zM2t6TdYNK2lTSeMl3QKMA3pJul7SaEnjJP2kaNl/SeovqUrSHElXSBor6VlJ62TLXC7p\nrKLlr5D0gqT/SBqUze8s6e/Z696VvVb/EiUOBc4CNpbUq6iW/SS9mL3+iGzeGpL+JumV7HZwodai\n5x0laVg2fbOk6yS9APxc0s7Ze3lJ0ihJm2XLVUm6WtJr2Xr/W9LXJN1VtN6vS7qzMX4nZma2Yla6\nZZljC+DYiBgNIOnciJglqQp4QtJdETG+1nO6Ak9FxLmSrgK+DVxRx7oVETtKOhD4CbAP8F1gWkQc\nKmlb4MW6ipLUF+gREWOyIDoCuEbSesB1wOCIeFdSj+wpFwMfRcQ2WSu5Wz3eey9g54iokdQ1W2e1\npH2Ay4Ejge8A6wPbRsSS7PXmAL+X1DNrtZ8A/KXE+zgFOAVgww03rEdJZma2Ipr6AJ+3C0GZGSrp\nRVKIfRHYso7nfBoRD2bTY4C+JdZ9dx3L7AbcDhARY0kt2rocBdyRTd9OamUC7AI8ERHvZuuYlc3f\n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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        },
        {
          "output_type": "display_data",
          "data": {
            "image/png": "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\n",
            "text/plain": [
              "<Figure size 432x288 with 1 Axes>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "LqL6FYUrtXpf",
        "colab_type": "code",
        "colab": {
          "resources": {
            "http://localhost:8080/nbextensions/google.colab/files.js": {
              "data": "Ly8gQ29weXJpZ2h0IDIwMTcgR29vZ2xlIExMQwovLwovLyBMaWNlbnNlZCB1bmRlciB0aGUgQXBhY2hlIExpY2Vuc2UsIFZlcnNpb24gMi4wICh0aGUgIkxpY2Vuc2UiKTsKLy8geW91IG1heSBub3QgdXNlIHRoaXMgZmlsZSBleGNlcHQgaW4gY29tcGxpYW5jZSB3aXRoIHRoZSBMaWNlbnNlLgovLyBZb3UgbWF5IG9idGFpbiBhIGNvcHkgb2YgdGhlIExpY2Vuc2UgYXQKLy8KLy8gICAgICBodHRwOi8vd3d3LmFwYWNoZS5vcmcvbGljZW5zZXMvTElDRU5TRS0yLjAKLy8KLy8gVW5sZXNzIHJlcXVpcmVkIGJ5IGFwcGxpY2FibGUgbGF3IG9yIGFncmVlZCB0byBpbiB3cml0aW5nLCBzb2Z0d2FyZQovLyBkaXN0cmlidXRlZCB1bmRlciB0aGUgTGljZW5zZSBpcyBkaXN0cmlidXRlZCBvbiBhbiAiQVMgSVMiIEJBU0lTLAovLyBXSVRIT1VUIFdBUlJBTlRJRVMgT1IgQ09ORElUSU9OUyBPRiBBTlkgS0lORCwgZWl0aGVyIGV4cHJlc3Mgb3IgaW1wbGllZC4KLy8gU2VlIHRoZSBMaWNlbnNlIGZvciB0aGUgc3BlY2lmaWMgbGFuZ3VhZ2UgZ292ZXJuaW5nIHBlcm1pc3Npb25zIGFuZAovLyBsaW1pdGF0aW9ucyB1bmRlciB0aGUgTGljZW5zZS4KCi8qKgogKiBAZmlsZW92ZXJ2aWV3IEhlbHBlcnMgZm9yIGdvb2dsZS5jb2xhYiBQeXRob24gbW9kdWxlLgogKi8KKGZ1bmN0aW9uKHNjb3BlKSB7CmZ1bmN0aW9uIHNwYW4odGV4dCwgc3R5bGVBdHRyaWJ1dGVzID0ge30pIHsKICBjb25zdCBlbGVtZW50ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc3BhbicpOwogIGVsZW1lbnQudGV4dENvbnRlbnQgPSB0ZXh0OwogIGZvciAoY29uc3Qga2V5IG9mIE9iamVjdC5rZXlzKHN0eWxlQXR0cmlidXRlcykpIHsKICAgIGVsZW1lbnQuc3R5bGVba2V5XSA9IHN0eWxlQXR0cmlidXRlc1trZXldOwogIH0KICByZXR1cm4gZWxlbWVudDsKfQoKLy8gTWF4IG51bWJlciBvZiBieXRlcyB3aGljaCB3aWxsIGJlIHVwbG9hZGVkIGF0IGEgdGltZS4KY29uc3QgTUFYX1BBWUxPQURfU0laRSA9IDEwMCAqIDEwMjQ7Ci8vIE1heCBhbW91bnQgb2YgdGltZSB0byBibG9jayB3YWl0aW5nIGZvciB0aGUgdXNlci4KY29uc3QgRklMRV9DSEFOR0VfVElNRU9VVF9NUyA9IDMwICogMTAwMDsKCmZ1bmN0aW9uIF91cGxvYWRGaWxlcyhpbnB1dElkLCBvdXRwdXRJZCkgewogIGNvbnN0IHN0ZXBzID0gdXBsb2FkRmlsZXNTdGVwKGlucHV0SWQsIG91dHB1dElkKTsKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIC8vIENhY2hlIHN0ZXBzIG9uIHRoZSBvdXRwdXRFbGVtZW50IHRvIG1ha2UgaXQgYXZhaWxhYmxlIGZvciB0aGUgbmV4dCBjYWxsCiAgLy8gdG8gdXBsb2FkRmlsZXNDb250aW51ZSBmcm9tIFB5dGhvbi4KICBvdXRwdXRFbGVtZW50LnN0ZXBzID0gc3RlcHM7CgogIHJldHVybiBfdXBsb2FkRmlsZXNDb250aW51ZShvdXRwdXRJZCk7Cn0KCi8vIFRoaXMgaXMgcm91Z2hseSBhbiBhc3luYyBnZW5lcmF0b3IgKG5vdCBzdXBwb3J0ZWQgaW4gdGhlIGJyb3dzZXIgeWV0KSwKLy8gd2hlcmUgdGhlcmUgYXJlIG11bHRpcGxlIGFzeW5jaHJvbm91cyBzdGVwcyBhbmQgdGhlIFB5dGhvbiBzaWRlIGlzIGdvaW5nCi8vIHRvIHBvbGwgZm9yIGNvbXBsZXRpb24gb2YgZWFjaCBzdGVwLgovLyBUaGlzIHVzZXMgYSBQcm9taXNlIHRvIGJsb2NrIHRoZSBweXRob24gc2lkZSBvbiBjb21wbGV0aW9uIG9mIGVhY2ggc3RlcCwKLy8gdGhlbiBwYXNzZXMgdGhlIHJlc3VsdCBvZiB0aGUgcHJldmlvdXMgc3RlcCBhcyB0aGUgaW5wdXQgdG8gdGhlIG5leHQgc3RlcC4KZnVuY3Rpb24gX3VwbG9hZEZpbGVzQ29udGludWUob3V0cHV0SWQpIHsKICBjb25zdCBvdXRwdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQob3V0cHV0SWQpOwogIGNvbnN0IHN0ZXBzID0gb3V0cHV0RWxlbWVudC5zdGVwczsKCiAgY29uc3QgbmV4dCA9IHN0ZXBzLm5leHQob3V0cHV0RWxlbWVudC5sYXN0UHJvbWlzZVZhbHVlKTsKICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5leHQudmFsdWUucHJvbWlzZSkudGhlbigodmFsdWUpID0+IHsKICAgIC8vIENhY2hlIHRoZSBsYXN0IHByb21pc2UgdmFsdWUgdG8gbWFrZSBpdCBhdmFpbGFibGUgdG8gdGhlIG5leHQKICAgIC8vIHN0ZXAgb2YgdGhlIGdlbmVyYXRvci4KICAgIG91dHB1dEVsZW1lbnQubGFzdFByb21pc2VWYWx1ZSA9IHZhbHVlOwogICAgcmV0dXJuIG5leHQudmFsdWUucmVzcG9uc2U7CiAgfSk7Cn0KCi8qKgogKiBHZW5lcmF0b3IgZnVuY3Rpb24gd2hpY2ggaXMgY2FsbGVkIGJldHdlZW4gZWFjaCBhc3luYyBzdGVwIG9mIHRoZSB1cGxvYWQKICogcHJvY2Vzcy4KICogQHBhcmFtIHtzdHJpbmd9IGlucHV0SWQgRWxlbWVudCBJRCBvZiB0aGUgaW5wdXQgZmlsZSBwaWNrZXIgZWxlbWVudC4KICogQHBhcmFtIHtzdHJpbmd9IG91dHB1dElkIEVsZW1lbnQgSUQgb2YgdGhlIG91dHB1dCBkaXNwbGF5LgogKiBAcmV0dXJuIHshSXRlcmFibGU8IU9iamVjdD59IEl0ZXJhYmxlIG9mIG5leHQgc3RlcHMuCiAqLwpmdW5jdGlvbiogdXBsb2FkRmlsZXNTdGVwKGlucHV0SWQsIG91dHB1dElkKSB7CiAgY29uc3QgaW5wdXRFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoaW5wdXRJZCk7CiAgaW5wdXRFbGVtZW50LmRpc2FibGVkID0gZmFsc2U7CgogIGNvbnN0IG91dHB1dEVsZW1lbnQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZChvdXRwdXRJZCk7CiAgb3V0cHV0RWxlbWVudC5pbm5lckhUTUwgPSAnJzsKCiAgY29uc3QgcGlja2VkUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICBpbnB1dEVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignY2hhbmdlJywgKGUpID0+IHsKICAgICAgcmVzb2x2ZShlLnRhcmdldC5maWxlcyk7CiAgICB9KTsKICB9KTsKCiAgY29uc3QgY2FuY2VsID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnYnV0dG9uJyk7CiAgaW5wdXRFbGVtZW50LnBhcmVudEVsZW1lbnQuYXBwZW5kQ2hpbGQoY2FuY2VsKTsKICBjYW5jZWwudGV4dENvbnRlbnQgPSAnQ2FuY2VsIHVwbG9hZCc7CiAgY29uc3QgY2FuY2VsUHJvbWlzZSA9IG5ldyBQcm9taXNlKChyZXNvbHZlKSA9PiB7CiAgICBjYW5jZWwub25jbGljayA9ICgpID0+IHsKICAgICAgcmVzb2x2ZShudWxsKTsKICAgIH07CiAgfSk7CgogIC8vIENhbmNlbCB1cGxvYWQgaWYgdXNlciBoYXNuJ3QgcGlja2VkIGFueXRoaW5nIGluIHRpbWVvdXQuCiAgY29uc3QgdGltZW91dFByb21pc2UgPSBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gewogICAgc2V0VGltZW91dCgoKSA9PiB7CiAgICAgIHJlc29sdmUobnVsbCk7CiAgICB9LCBGSUxFX0NIQU5HRV9USU1FT1VUX01TKTsKICB9KTsKCiAgLy8gV2FpdCBmb3IgdGhlIHVzZXIgdG8gcGljayB0aGUgZmlsZXMuCiAgY29uc3QgZmlsZXMgPSB5aWVsZCB7CiAgICBwcm9taXNlOiBQcm9taXNlLnJhY2UoW3BpY2tlZFByb21pc2UsIHRpbWVvdXRQcm9taXNlLCBjYW5jZWxQcm9taXNlXSksCiAgICByZXNwb25zZTogewogICAgICBhY3Rpb246ICdzdGFydGluZycsCiAgICB9CiAgfTsKCiAgaWYgKCFmaWxlcykgewogICAgcmV0dXJuIHsKICAgICAgcmVzcG9uc2U6IHsKICAgICAgICBhY3Rpb246ICdjb21wbGV0ZScsCiAgICAgIH0KICAgIH07CiAgfQoKICBjYW5jZWwucmVtb3ZlKCk7CgogIC8vIERpc2FibGUgdGhlIGlucHV0IGVsZW1lbnQgc2luY2UgZnVydGhlciBwaWNrcyBhcmUgbm90IGFsbG93ZWQuCiAgaW5wdXRFbGVtZW50LmRpc2FibGVkID0gdHJ1ZTsKCiAgZm9yIChjb25zdCBmaWxlIG9mIGZpbGVzKSB7CiAgICBjb25zdCBsaSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xpJyk7CiAgICBsaS5hcHBlbmQoc3BhbihmaWxlLm5hbWUsIHtmb250V2VpZ2h0OiAnYm9sZCd9KSk7CiAgICBsaS5hcHBlbmQoc3BhbigKICAgICAgICBgKCR7ZmlsZS50eXBlIHx8ICduL2EnfSkgLSAke2ZpbGUuc2l6ZX0gYnl0ZXMsIGAgKwogICAgICAgIGBsYXN0IG1vZGlmaWVkOiAkewogICAgICAgICAgICBmaWxlLmxhc3RNb2RpZmllZERhdGUgPyBmaWxlLmxhc3RNb2RpZmllZERhdGUudG9Mb2NhbGVEYXRlU3RyaW5nKCkgOgogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnbi9hJ30gLSBgKSk7CiAgICBjb25zdCBwZXJjZW50ID0gc3BhbignMCUgZG9uZScpOwogICAgbGkuYXBwZW5kQ2hpbGQocGVyY2VudCk7CgogICAgb3V0cHV0RWxlbWVudC5hcHBlbmRDaGlsZChsaSk7CgogICAgY29uc3QgZmlsZURhdGFQcm9taXNlID0gbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHsKICAgICAgY29uc3QgcmVhZGVyID0gbmV3IEZpbGVSZWFkZXIoKTsKICAgICAgcmVhZGVyLm9ubG9hZCA9IChlKSA9PiB7CiAgICAgICAgcmVzb2x2ZShlLnRhcmdldC5yZXN1bHQpOwogICAgICB9OwogICAgICByZWFkZXIucmVhZEFzQXJyYXlCdWZmZXIoZmlsZSk7CiAgICB9KTsKICAgIC8vIFdhaXQgZm9yIHRoZSBkYXRhIHRvIGJlIHJlYWR5LgogICAgbGV0IGZpbGVEYXRhID0geWllbGQgewogICAgICBwcm9taXNlOiBmaWxlRGF0YVByb21pc2UsCiAgICAgIHJlc3BvbnNlOiB7CiAgICAgICAgYWN0aW9uOiAnY29udGludWUnLAogICAgICB9CiAgICB9OwoKICAgIC8vIFVzZSBhIGNodW5rZWQgc2VuZGluZyB0byBhdm9pZCBtZXNzYWdlIHNpemUgbGltaXRzLiBTZWUgYi82MjExNTY2MC4KICAgIGxldCBwb3NpdGlvbiA9IDA7CiAgICB3aGlsZSAocG9zaXRpb24gPCBmaWxlRGF0YS5ieXRlTGVuZ3RoKSB7CiAgICAgIGNvbnN0IGxlbmd0aCA9IE1hdGgubWluKGZpbGVEYXRhLmJ5dGVMZW5ndGggLSBwb3NpdGlvbiwgTUFYX1BBWUxPQURfU0laRSk7CiAgICAgIGNvbnN0IGNodW5rID0gbmV3IFVpbnQ4QXJyYXkoZmlsZURhdGEsIHBvc2l0aW9uLCBsZW5ndGgpOwogICAgICBwb3NpdGlvbiArPSBsZW5ndGg7CgogICAgICBjb25zdCBiYXNlNjQgPSBidG9hKFN0cmluZy5mcm9tQ2hhckNvZGUuYXBwbHkobnVsbCwgY2h1bmspKTsKICAgICAgeWllbGQgewogICAgICAgIHJlc3BvbnNlOiB7CiAgICAgICAgICBhY3Rpb246ICdhcHBlbmQnLAogICAgICAgICAgZmlsZTogZmlsZS5uYW1lLAogICAgICAgICAgZGF0YTogYmFzZTY0LAogICAgICAgIH0sCiAgICAgIH07CiAgICAgIHBlcmNlbnQudGV4dENvbnRlbnQgPQogICAgICAgICAgYCR7TWF0aC5yb3VuZCgocG9zaXRpb24gLyBmaWxlRGF0YS5ieXRlTGVuZ3RoKSAqIDEwMCl9JSBkb25lYDsKICAgIH0KICB9CgogIC8vIEFsbCBkb25lLgogIHlpZWxkIHsKICAgIHJlc3BvbnNlOiB7CiAgICAgIGFjdGlvbjogJ2NvbXBsZXRlJywKICAgIH0KICB9Owp9CgpzY29wZS5nb29nbGUgPSBzY29wZS5nb29nbGUgfHwge307CnNjb3BlLmdvb2dsZS5jb2xhYiA9IHNjb3BlLmdvb2dsZS5jb2xhYiB8fCB7fTsKc2NvcGUuZ29vZ2xlLmNvbGFiLl9maWxlcyA9IHsKICBfdXBsb2FkRmlsZXMsCiAgX3VwbG9hZEZpbGVzQ29udGludWUsCn07Cn0pKHNlbGYpOwo=",
              "ok": true,
              "headers": [
                [
                  "content-type",
                  "application/javascript"
                ]
              ],
              "status": 200,
              "status_text": ""
            }
          },
          "base_uri": "https://localhost:8080/",
          "height": 57
        },
        "outputId": "bcf81408-9d23-42df-e47c-7a2cd7d00ba1"
      },
      "source": [
        "# Here's a codeblock just for fun. You should be able to upload an image here \n",
        "# and have it classified without crashing\n",
        "\n",
        "import numpy as np\n",
        "from google.colab import files\n",
        "from keras.preprocessing import image\n",
        "\n",
        "uploaded = files.upload()\n",
        "\n",
        "for fn in uploaded.keys():\n",
        " \n",
        "  # predicting images\n",
        "  path = '/content/' + fn\n",
        "  img = image.load_img(path, target_size=(150, 150))\n",
        "  x = image.img_to_array(img)\n",
        "  x = np.expand_dims(x, axis=0)\n",
        "\n",
        "  images = np.vstack([x])\n",
        "  classes = model.predict(images, batch_size=10)\n",
        "  print(classes[0])\n",
        "  if classes[0]>0.5:\n",
        "    print(fn + \" is a dog\")\n",
        "  else:\n",
        "    print(fn + \" is a cat\")"
      ],
      "execution_count": 14,
      "outputs": [
        {
          "output_type": "stream",
          "text": [
            "Using TensorFlow backend.\n"
          ],
          "name": "stderr"
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "\n",
              "     <input type=\"file\" id=\"files-eb9630b6-6336-4716-bf2f-fa38a1a77cf2\" name=\"files[]\" multiple disabled />\n",
              "     <output id=\"result-eb9630b6-6336-4716-bf2f-fa38a1a77cf2\">\n",
              "      Upload widget is only available when the cell has been executed in the\n",
              "      current browser session. Please rerun this cell to enable.\n",
              "      </output>\n",
              "      <script src=\"/nbextensions/google.colab/files.js\"></script> "
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {
            "tags": []
          }
        }
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "id": "aMK8nW8Ix2oG",
        "colab_type": "code",
        "colab": {}
      },
      "source": [
        ""
      ],
      "execution_count": 0,
      "outputs": []
    }
  ]
}